import { SetupContext, ref } from "vue";
import { ListViewProps } from "../list-view.props";
import { UseDataView, UseDraggable, UseHover } from "./types";

export function useDraggable(
    props: ListViewProps,
    context: SetupContext,
    dataViewComposition: UseDataView,
    useHoverComposition: UseHover
): UseDraggable {
    const identifyField = ref(props.idField);
    const { dataView } = dataViewComposition;
    const draggingIndex = ref(-1);
    const isDragging = ref(false);
    const { activeIndex, focusedItemId, hoverIndex, resumeHover, suspendHover } = useHoverComposition;

    function dragstart(e: DragEvent, targetItem: any, index: number) {
        e.stopPropagation();
        suspendHover();
        if (targetItem) {
            setTimeout(() => {
                draggingIndex.value = index;
                isDragging.value = true;
                targetItem.moving = true;
            });
        }
    }

    function dragenter(e: DragEvent, index: number) {
        e.preventDefault();
        if (draggingIndex.value !== index) {
            const draggingItem = dataView.value[draggingIndex.value];
            const reOrderedItems = dataView.value;
            reOrderedItems.splice(draggingIndex.value, 1);
            reOrderedItems.splice(index, 0, draggingItem);
            draggingIndex.value = index;
        }
    }
    function dragover(e: DragEvent, index: number) {
        e.preventDefault();
        if (e.dataTransfer) {
            e.dataTransfer.dropEffect = 'move';
        }
    }

    function dragend(e: DragEvent, targetItem: any) {
        if (targetItem) {
            targetItem.moving = false;
        }
        dataView.value.forEach((dataItem: any, index: number) => { dataItem.__fv_index__ = index; });
        isDragging.value = false;
        resumeHover();
        hoverIndex.value = targetItem.__fv_index__;
        activeIndex.value = targetItem.__fv_index__;
        focusedItemId.value = targetItem[identifyField.value];
        context.emit('change', dataView.value);
    }

    return {
        dragstart,
        dragenter,
        dragover,
        dragend,
        isDragging
    };
}
